{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>Quick Start: Creating Sample-wise Unlearnable Examples</h2>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Prepare Data</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "from torch.utils.data import DataLoader\n",
    "from torchvision import datasets, transforms\n",
    "\n",
    "# Prepare Dataset\n",
    "train_transform = [\n",
    "    transforms.ToTensor()\n",
    "]\n",
    "test_transform = [\n",
    "    transforms.ToTensor()\n",
    "]\n",
    "train_transform = transforms.Compose(train_transform)\n",
    "test_transform = transforms.Compose(test_transform)\n",
    "\n",
    "clean_train_dataset = datasets.CIFAR10(root='../datasets', train=True, download=True, transform=train_transform)\n",
    "clean_test_dataset = datasets.CIFAR10(root='../datasets', train=False, download=True, transform=test_transform)\n",
    "\n",
    "clean_train_loader = DataLoader(dataset=clean_train_dataset, batch_size=512,\n",
    "                                shuffle=False, pin_memory=True,\n",
    "                                drop_last=False, num_workers=12)\n",
    "clean_test_loader = DataLoader(dataset=clean_test_dataset, batch_size=512,\n",
    "                                shuffle=False, pin_memory=True,\n",
    "                                drop_last=False, num_workers=12)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Prepare Model</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from models.ResNet import ResNet18\n",
    "import toolbox\n",
    "\n",
    "torch.backends.cudnn.enabled = True\n",
    "torch.backends.cudnn.benchmark = True\n",
    "\n",
    "base_model = ResNet18()\n",
    "base_model = base_model.cuda()\n",
    "criterion = torch.nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.SGD(params=base_model.parameters(), lr=0.1, weight_decay=0.0005, momentum=0.9)\n",
    "\n",
    "noise_generator = toolbox.PerturbationTool(epsilon=0.03137254901960784, num_steps=20, step_size=0.0031372549019607846)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Generate Error-Minimizing Noise</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:05<00:00,  1.89s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 8.13\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:06<00:00,  1.91s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 11.89\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:07<00:00,  1.91s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 31.45\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:07<00:00,  1.91s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 67.06\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:08<00:00,  1.92s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 88.17\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:07<00:00,  1.91s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 68.22\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:07<00:00,  1.91s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 53.30\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:08<00:00,  1.92s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 96.87\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:07<00:00,  1.92s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 97.75\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 98/98 [03:07<00:00,  1.91s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy 99.72\n"
     ]
    }
   ],
   "source": [
    "from tqdm import tqdm\n",
    "\n",
    "noise = torch.zeros([50000, 3, 32, 32])\n",
    "data_iter = iter(clean_train_loader)\n",
    "condition = True\n",
    "train_idx = 0\n",
    "\n",
    "while condition:\n",
    "    # optimize theta for M steps\n",
    "    base_model.train()\n",
    "    for param in base_model.parameters():\n",
    "        param.requires_grad = True\n",
    "    for j in range(0, 10):\n",
    "        try:\n",
    "            (images, labels) = next(data_iter)\n",
    "        except:\n",
    "            train_idx = 0\n",
    "            data_iter = iter(clean_train_loader)\n",
    "            (images, labels) = next(data_iter)\n",
    "        \n",
    "        for i, _ in enumerate(images):\n",
    "            # Update noise to images\n",
    "            images[i] += noise[train_idx]\n",
    "            train_idx += 1\n",
    "        images, labels = images.cuda(), labels.cuda()\n",
    "        base_model.zero_grad()\n",
    "        optimizer.zero_grad()\n",
    "        logits = base_model(images)\n",
    "        loss = criterion(logits, labels)\n",
    "        loss.backward()\n",
    "        torch.nn.utils.clip_grad_norm_(base_model.parameters(), 5.0)\n",
    "        optimizer.step()\n",
    "    \n",
    "    # Perturbation over entire dataset\n",
    "    idx = 0\n",
    "    for param in base_model.parameters():\n",
    "        param.requires_grad = False\n",
    "    for i, (images, labels) in tqdm(enumerate(clean_train_loader), total=len(clean_train_loader)):\n",
    "        batch_start_idx, batch_noise = idx, []\n",
    "        for i, _ in enumerate(images):\n",
    "            # Update noise to images\n",
    "            batch_noise.append(noise[idx])\n",
    "            idx += 1\n",
    "        batch_noise = torch.stack(batch_noise).cuda()\n",
    "        \n",
    "        # Update sample-wise perturbation\n",
    "        base_model.eval()\n",
    "        images, labels = images.cuda(), labels.cuda()\n",
    "        perturb_img, eta = noise_generator.min_min_attack(images, labels, base_model, optimizer, criterion, \n",
    "                                                          random_noise=batch_noise)\n",
    "        for i, delta in enumerate(eta):\n",
    "            noise[batch_start_idx+i] = delta.clone().detach().cpu()\n",
    "        \n",
    "    # Eval stop condition\n",
    "    eval_idx, total, correct = 0, 0, 0\n",
    "    for i, (images, labels) in enumerate(clean_train_loader):\n",
    "        for i, _ in enumerate(images):\n",
    "            # Update noise to images\n",
    "            images[i] += noise[eval_idx]\n",
    "            eval_idx += 1\n",
    "        images, labels = images.cuda(), labels.cuda()\n",
    "        with torch.no_grad():\n",
    "            logits = base_model(images)\n",
    "            _, predicted = torch.max(logits.data, 1)\n",
    "            total += labels.size(0)\n",
    "            correct += (predicted == labels).sum().item()\n",
    "    acc = correct / total\n",
    "    print('Accuracy %.2f' % (acc*100))\n",
    "    if acc > 0.99:\n",
    "        condition=False      \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[[[ 2.5098e-02,  3.1373e-02,  2.8235e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [-9.4118e-03,  1.8824e-02, -1.2549e-02,  ..., -2.8235e-02,\n",
      "           -2.8235e-02, -2.8235e-02],\n",
      "          [-2.1961e-02, -3.1373e-02, -3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          ...,\n",
      "          [ 3.1370e-03, -2.1961e-02, -2.8235e-02,  ...,  6.2747e-03,\n",
      "            1.2549e-02,  2.5098e-02],\n",
      "          [-3.1370e-03,  9.4119e-03,  9.4119e-03,  ...,  2.3842e-07,\n",
      "           -2.5098e-02, -3.1373e-02],\n",
      "          [-3.1370e-03,  3.1375e-03, -1.5686e-02,  ..., -6.2742e-03,\n",
      "           -2.3842e-07, -1.5686e-02]],\n",
      "\n",
      "         [[-3.1373e-02, -5.9605e-08, -2.8235e-02,  ...,  3.1371e-03,\n",
      "           -1.5686e-02, -2.1961e-02],\n",
      "          [-3.1373e-02,  1.2549e-02,  6.2745e-03,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [ 3.1373e-02,  2.5098e-02,  2.5098e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          ...,\n",
      "          [-3.1373e-02,  1.8823e-02,  9.4115e-03,  ..., -1.8824e-02,\n",
      "            9.4117e-03,  2.1961e-02],\n",
      "          [ 3.1370e-03, -6.2745e-03, -9.4119e-03,  ...,  3.1373e-02,\n",
      "            2.5098e-02,  2.8235e-02],\n",
      "          [ 1.2549e-02,  2.1961e-02,  1.5686e-02,  ...,  1.2549e-02,\n",
      "            2.5098e-02,  3.1373e-02]],\n",
      "\n",
      "         [[ 3.1373e-02, -2.5098e-02, -2.5098e-02,  ..., -2.8235e-02,\n",
      "           -2.8235e-02, -2.8235e-02],\n",
      "          [ 3.1373e-02,  0.0000e+00,  1.2549e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-1.8823e-02,  0.0000e+00, -3.1373e-02,  ..., -1.8824e-02,\n",
      "           -1.8824e-02,  2.8235e-02],\n",
      "          ...,\n",
      "          [-2.1961e-02, -2.8235e-02, -2.5098e-02,  ..., -3.1373e-02,\n",
      "           -2.7451e-02, -2.8235e-02],\n",
      "          [ 3.1373e-02,  3.1372e-03,  3.1373e-02,  ..., -3.1373e-02,\n",
      "           -1.2549e-02, -1.8824e-02],\n",
      "          [ 9.4117e-03,  1.5686e-02, -2.8235e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02]]],\n",
      "\n",
      "\n",
      "        [[[-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  2.5098e-02],\n",
      "          ...,\n",
      "          [-2.3842e-07,  6.2742e-03, -1.8824e-02,  ..., -2.5098e-02,\n",
      "           -2.5098e-02, -2.5098e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -2.8235e-02,\n",
      "           -2.8235e-02, -2.8235e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -2.8235e-02,\n",
      "           -2.8235e-02, -2.8235e-02]],\n",
      "\n",
      "         [[ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [-1.2549e-02, -3.1373e-02,  1.8824e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          ...,\n",
      "          [ 1.2549e-02,  6.2747e-03,  2.5098e-02,  ...,  2.5098e-02,\n",
      "            1.2549e-02,  3.1373e-02],\n",
      "          [ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ...,  2.8235e-02,\n",
      "            2.8235e-02,  2.8235e-02],\n",
      "          [ 2.8235e-02,  3.1373e-02,  3.1373e-02,  ...,  2.8235e-02,\n",
      "            2.8235e-02,  2.8235e-02]],\n",
      "\n",
      "         [[-2.1960e-02, -3.1373e-02, -3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-3.1373e-02, -1.2549e-02, -3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [-1.8824e-02,  2.5098e-02,  1.8824e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          ...,\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -2.8235e-02,\n",
      "           -2.8235e-02, -2.8235e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -2.8235e-02,\n",
      "           -2.8235e-02, -2.8235e-02],\n",
      "          [ 1.2549e-02,  6.2746e-03, -3.1373e-02,  ..., -2.8235e-02,\n",
      "           -3.1373e-02, -3.1373e-02]]],\n",
      "\n",
      "\n",
      "        [[[-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -3.1373e-02,\n",
      "            1.0980e-02,  1.0980e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ...,  3.1372e-03,\n",
      "            3.1372e-03,  3.1372e-03],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ...,  7.0588e-03,\n",
      "            7.0588e-03,  7.0588e-03],\n",
      "          ...,\n",
      "          [ 5.9605e-08, -6.2745e-03, -1.2549e-02,  ..., -1.2549e-02,\n",
      "           -2.5098e-02, -6.2745e-03],\n",
      "          [-2.5098e-02, -1.8824e-02,  6.2746e-03,  ...,  1.2549e-02,\n",
      "            1.2549e-02,  6.2746e-03],\n",
      "          [-1.2549e-02, -1.8824e-02,  3.1373e-02,  ...,  5.9605e-08,\n",
      "            5.9605e-08, -6.2745e-03]],\n",
      "\n",
      "         [[ 3.1372e-03,  1.0980e-02,  1.0980e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [ 3.1372e-03,  3.1372e-03,  3.1372e-03,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-2.5098e-02, -1.4902e-02,  7.0588e-03,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          ...,\n",
      "          [ 6.2745e-03,  1.2549e-02,  1.2549e-02,  ..., -6.2746e-03,\n",
      "           -6.2746e-03, -5.9605e-08],\n",
      "          [ 1.8824e-02,  2.5098e-02, -5.9605e-08,  ..., -1.2549e-02,\n",
      "            1.2549e-02,  2.5098e-02],\n",
      "          [-6.2746e-03,  3.1373e-02, -3.1373e-02,  ..., -5.9605e-08,\n",
      "           -6.2746e-03,  2.8235e-02]],\n",
      "\n",
      "         [[-3.1373e-02, -3.1373e-02, -3.1373e-02,  ...,  1.0980e-02,\n",
      "            1.0980e-02,  1.0980e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ...,  3.1372e-03,\n",
      "            3.1372e-03,  3.1372e-03],\n",
      "          [-6.2747e-03, -3.1373e-02, -3.1373e-02,  ...,  7.0588e-03,\n",
      "            7.0588e-03,  7.0588e-03],\n",
      "          ...,\n",
      "          [-6.2745e-03, -6.2745e-03, -6.2745e-03,  ..., -2.8235e-02,\n",
      "           -2.8235e-02, -2.5098e-02],\n",
      "          [ 1.2549e-02,  1.8824e-02,  1.2549e-02,  ..., -2.1961e-02,\n",
      "           -2.5098e-02, -2.8235e-02],\n",
      "          [-2.5098e-02, -3.1373e-02, -1.8824e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -1.8824e-02]]],\n",
      "\n",
      "\n",
      "        ...,\n",
      "\n",
      "\n",
      "        [[[ 6.2745e-03,  1.2549e-02, -3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [-4.4703e-08, -2.8235e-02, -3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [-2.5098e-02, -2.5098e-02, -2.5098e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          ...,\n",
      "          [ 1.2549e-02,  6.2746e-03, -6.2745e-03,  ..., -6.2745e-03,\n",
      "           -6.2745e-03, -6.2745e-03],\n",
      "          [-6.2745e-03, -6.2745e-03,  5.9605e-08,  ..., -2.2352e-08,\n",
      "           -1.4901e-08, -2.3529e-03],\n",
      "          [-3.1373e-02, -3.1373e-02, -1.8824e-02,  ..., -2.5098e-02,\n",
      "           -2.5098e-02, -2.5098e-02]],\n",
      "\n",
      "         [[-1.2549e-02,  1.8823e-02,  3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [ 1.2549e-02,  1.2549e-02, -6.2742e-03,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          ...,\n",
      "          [-1.8824e-02,  6.2745e-03,  6.2745e-03,  ...,  6.2745e-03,\n",
      "            6.2745e-03,  6.2745e-03],\n",
      "          [-5.9605e-08, -5.9605e-08, -5.9605e-08,  ..., -5.9605e-08,\n",
      "            6.2745e-03,  1.2549e-02],\n",
      "          [ 3.1373e-02,  2.1961e-02,  1.2549e-02,  ...,  2.5098e-02,\n",
      "            2.5098e-02,  2.5098e-02]],\n",
      "\n",
      "         [[ 1.2549e-02, -3.1373e-02, -3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [ 3.1373e-02, -3.1375e-03,  3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [ 3.1373e-02,  1.4902e-02,  3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          ...,\n",
      "          [-6.2745e-03, -6.2745e-03, -6.2745e-03,  ..., -2.5098e-02,\n",
      "           -2.8235e-02, -2.5098e-02],\n",
      "          [ 5.9605e-08, -1.5686e-02, -1.2549e-02,  ..., -2.8235e-02,\n",
      "           -2.5098e-02, -6.2746e-03],\n",
      "          [-1.8824e-02, -2.8235e-02, -2.8235e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02]]],\n",
      "\n",
      "\n",
      "        [[[ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          ...,\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ...,  3.1370e-03,\n",
      "           -2.3842e-07, -2.3842e-07],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -1.8824e-02,\n",
      "           -1.8824e-02, -1.8824e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -1.8824e-02,\n",
      "           -1.8824e-02, -1.8824e-02]],\n",
      "\n",
      "         [[-3.1373e-02, -3.1373e-02, -3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          [ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  3.1373e-02],\n",
      "          ...,\n",
      "          [ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ...,  9.4119e-03,\n",
      "           -9.4115e-03,  1.2549e-02],\n",
      "          [ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ...,  1.8824e-02,\n",
      "            1.8824e-02,  1.8824e-02],\n",
      "          [ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ...,  1.8824e-02,\n",
      "            1.8824e-02,  1.8824e-02]],\n",
      "\n",
      "         [[ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [ 3.1372e-02, -3.1373e-02,  3.1372e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          ...,\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -1.8824e-02,\n",
      "           -1.8824e-02,  2.8235e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -1.8824e-02,\n",
      "           -1.8824e-02, -1.8824e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -3.1373e-02,  ..., -1.8824e-02,\n",
      "           -1.8824e-02, -1.8824e-02]]],\n",
      "\n",
      "\n",
      "        [[[ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ..., -2.5098e-02,\n",
      "           -2.5098e-02, -3.1373e-02],\n",
      "          [ 3.1373e-02,  3.1373e-02,  2.8235e-02,  ..., -2.5098e-02,\n",
      "           -2.5098e-02, -2.5098e-02],\n",
      "          [ 3.1372e-02,  1.8823e-02, -3.1373e-02,  ..., -2.5098e-02,\n",
      "           -2.5098e-02, -2.5098e-02],\n",
      "          ...,\n",
      "          [-2.5098e-02, -2.5098e-02, -2.5098e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-2.5098e-02, -2.5098e-02, -2.5098e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1372e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -2.5098e-02,  ...,  2.8235e-02,\n",
      "            2.8235e-02,  2.8235e-02]],\n",
      "\n",
      "         [[-3.1373e-02, -3.1373e-02, -2.8235e-02,  ...,  2.5098e-02,\n",
      "            2.5098e-02,  3.1373e-02],\n",
      "          [-3.1373e-02, -3.1373e-02, -2.3842e-07,  ...,  2.5098e-02,\n",
      "            2.5098e-02,  3.1373e-02],\n",
      "          [-6.2742e-03,  2.5098e-02,  3.1373e-02,  ...,  2.5098e-02,\n",
      "            2.5098e-02,  2.5098e-02],\n",
      "          ...,\n",
      "          [ 2.5098e-02,  2.5098e-02,  2.5098e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  2.8235e-02],\n",
      "          [ 2.5098e-02,  2.5098e-02,  2.5098e-02,  ...,  3.1373e-02,\n",
      "            3.1373e-02,  2.8235e-02],\n",
      "          [ 3.1373e-02,  3.1373e-02,  3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02]],\n",
      "\n",
      "         [[ 1.8823e-02,  2.8235e-02,  6.2742e-03,  ..., -2.5098e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-1.2549e-02, -3.1373e-02, -3.1373e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-2.5098e-02, -2.5098e-02, -2.5098e-02,  ..., -2.5098e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          ...,\n",
      "          [-2.5098e-02, -2.5098e-02, -2.5098e-02,  ..., -2.8235e-02,\n",
      "           -2.8235e-02, -2.8235e-02],\n",
      "          [-2.5098e-02, -2.5098e-02, -2.5098e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02],\n",
      "          [-3.1373e-02, -2.5098e-02, -2.5098e-02,  ..., -3.1373e-02,\n",
      "           -3.1373e-02, -3.1373e-02]]]])\n"
     ]
    }
   ],
   "source": [
    "# Examine the noise\n",
    "print(noise)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Creat Unlearnable Dataset</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# Add standard augmentation\n",
    "train_transform = [\n",
    "    transforms.RandomCrop(32, padding=4),\n",
    "    transforms.RandomHorizontalFlip(),\n",
    "    transforms.ToTensor()\n",
    "]\n",
    "train_transform = transforms.Compose(train_transform)\n",
    "clean_train_dataset = datasets.CIFAR10(root='../datasets', train=True, download=True, transform=train_transform)\n",
    "unlearnable_train_dataset = datasets.CIFAR10(root='../datasets', train=True, download=True, transform=train_transform)\n",
    "\n",
    "perturb_noise = noise.mul(255).clamp_(0, 255).permute(0, 2, 3, 1).to('cpu').numpy()\n",
    "unlearnable_train_dataset.data = unlearnable_train_dataset.data.astype(np.float32)\n",
    "for i in range(len(unlearnable_train_dataset)):\n",
    "    unlearnable_train_dataset.data[i] += perturb_noise[i]\n",
    "    unlearnable_train_dataset.data[i] = np.clip(unlearnable_train_dataset.data[i], a_min=0, a_max=255)\n",
    "unlearnable_train_dataset.data = unlearnable_train_dataset.data.astype(np.uint8)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Visualize Clean Images, Error-Minimizing Noise, Unlearnable Images</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x640 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import random\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib\n",
    "%matplotlib inline\n",
    "\n",
    "def imshow(img):\n",
    "    fig = plt.figure(figsize=(8, 8), dpi=80, facecolor='w', edgecolor='k')\n",
    "    npimg = img.numpy()\n",
    "    plt.imshow(np.transpose(npimg, (1, 2, 0)))\n",
    "    plt.show()\n",
    "    \n",
    "def get_pairs_of_imgs(idx):\n",
    "    clean_img = clean_train_dataset.data[idx]\n",
    "    unlearnable_img = unlearnable_train_dataset.data[idx]\n",
    "    clean_img = torchvision.transforms.functional.to_tensor(clean_img)\n",
    "    unlearnable_img = torchvision.transforms.functional.to_tensor(unlearnable_img)\n",
    "\n",
    "    x = noise[idx]\n",
    "    x_min = torch.min(x)\n",
    "    x_max = torch.max(x)\n",
    "    noise_norm = (x - x_min) / (x_max - x_min)\n",
    "    noise_norm = torch.clamp(noise_norm, 0, 1)\n",
    "    return [clean_img, noise_norm, unlearnable_img]\n",
    "    \n",
    "selected_idx = [random.randint(0, 50000) for _ in range(3)]\n",
    "img_grid = []\n",
    "for idx in selected_idx:\n",
    "    img_grid += get_pairs_of_imgs(idx)\n",
    "    \n",
    "\n",
    "imshow(torchvision.utils.make_grid(torch.stack(img_grid), nrow=3, pad_value=255))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Train ResNet18 on Unlearnable Dataset</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 36.99 Loss: 1.73: 100%|██████████| 391/391 [00:20<00:00, 19.17it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 35.16\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 76.95 Loss: 0.65: 100%|██████████| 391/391 [00:20<00:00, 19.51it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 22.21\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 93.06 Loss: 0.21: 100%|██████████| 391/391 [00:20<00:00, 19.51it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 23.69\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 95.13 Loss: 0.15: 100%|██████████| 391/391 [00:20<00:00, 19.37it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 25.79\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 96.16 Loss: 0.12: 100%|██████████| 391/391 [00:20<00:00, 19.23it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 20.87\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 96.78 Loss: 0.10: 100%|██████████| 391/391 [00:19<00:00, 19.56it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 19.92\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 96.89 Loss: 0.10: 100%|██████████| 391/391 [00:19<00:00, 19.65it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 19.44\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 97.22 Loss: 0.08: 100%|██████████| 391/391 [00:20<00:00, 19.45it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 19.08\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 97.35 Loss: 0.08: 100%|██████████| 391/391 [00:20<00:00, 19.47it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 22.07\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 97.58 Loss: 0.07: 100%|██████████| 391/391 [00:20<00:00, 19.37it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 17.37\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 97.89 Loss: 0.07: 100%|██████████| 391/391 [00:20<00:00, 19.43it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 20.82\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 97.85 Loss: 0.07: 100%|██████████| 391/391 [00:19<00:00, 19.56it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 18.45\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 98.05 Loss: 0.06: 100%|██████████| 391/391 [00:19<00:00, 19.59it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 19.74\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 98.18 Loss: 0.06: 100%|██████████| 391/391 [00:20<00:00, 19.30it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 19.36\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 98.30 Loss: 0.05: 100%|██████████| 391/391 [00:19<00:00, 19.55it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 22.84\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 98.53 Loss: 0.05: 100%|██████████| 391/391 [00:20<00:00, 19.44it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 22.93\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 98.61 Loss: 0.04: 100%|██████████| 391/391 [00:20<00:00, 19.52it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 16.04\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.00 Loss: 0.03: 100%|██████████| 391/391 [00:20<00:00, 19.43it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 17.80\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.08 Loss: 0.03: 100%|██████████| 391/391 [00:20<00:00, 19.33it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 22.51\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.22 Loss: 0.02: 100%|██████████| 391/391 [00:20<00:00, 19.32it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 23.77\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.44 Loss: 0.02: 100%|██████████| 391/391 [00:20<00:00, 19.22it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 23.28\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.57 Loss: 0.02: 100%|██████████| 391/391 [00:20<00:00, 19.13it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 19.66\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.60 Loss: 0.01: 100%|██████████| 391/391 [00:19<00:00, 19.64it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 25.13\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.76 Loss: 0.01: 100%|██████████| 391/391 [00:20<00:00, 19.43it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 23.19\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.83 Loss: 0.01: 100%|██████████| 391/391 [00:19<00:00, 19.55it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 22.05\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.89 Loss: 0.01: 100%|██████████| 391/391 [00:19<00:00, 19.56it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 22.94\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.88 Loss: 0.00: 100%|██████████| 391/391 [00:20<00:00, 19.42it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 23.66\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.94 Loss: 0.00: 100%|██████████| 391/391 [00:20<00:00, 19.44it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 23.19\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.95 Loss: 0.00: 100%|██████████| 391/391 [00:20<00:00, 19.53it/s]\n",
      "  0%|          | 0/391 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 22.83\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Acc 99.94 Loss: 0.00: 100%|██████████| 391/391 [00:20<00:00, 19.46it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Clean Accuracy 23.60\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from util import AverageMeter\n",
    "\n",
    "model = ResNet18()\n",
    "model = model.cuda()\n",
    "criterion = torch.nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.SGD(params=model.parameters(), lr=0.1, weight_decay=0.0005, momentum=0.9)\n",
    "scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=30, eta_min=0)\n",
    "\n",
    "unlearnable_loader = DataLoader(dataset=unlearnable_train_dataset, batch_size=128,\n",
    "                                shuffle=True, pin_memory=True,\n",
    "                                drop_last=False, num_workers=12)\n",
    "\n",
    "\n",
    "for epoch in range(30):\n",
    "    # Train\n",
    "    model.train()\n",
    "    acc_meter = AverageMeter()\n",
    "    loss_meter = AverageMeter()\n",
    "    pbar = tqdm(unlearnable_loader, total=len(unlearnable_loader))\n",
    "    for images, labels in pbar:\n",
    "        images, labels = images.cuda(), labels.cuda()\n",
    "        model.zero_grad()\n",
    "        optimizer.zero_grad()\n",
    "        logits = model(images)\n",
    "        loss = criterion(logits, labels)\n",
    "        loss.backward()\n",
    "        torch.nn.utils.clip_grad_norm_(model.parameters(), 5.0)\n",
    "        optimizer.step()\n",
    "        \n",
    "        _, predicted = torch.max(logits.data, 1)\n",
    "        acc = (predicted == labels).sum().item()/labels.size(0)\n",
    "        acc_meter.update(acc)\n",
    "        loss_meter.update(loss.item())\n",
    "        pbar.set_description(\"Acc %.2f Loss: %.2f\" % (acc_meter.avg*100, loss_meter.avg))\n",
    "    scheduler.step()\n",
    "    # Eval\n",
    "    model.eval()\n",
    "    correct, total = 0, 0\n",
    "    for i, (images, labels) in enumerate(clean_test_loader):\n",
    "        images, labels = images.cuda(), labels.cuda()\n",
    "        with torch.no_grad():\n",
    "            logits = model(images)\n",
    "            _, predicted = torch.max(logits.data, 1)\n",
    "            total += labels.size(0)\n",
    "            correct += (predicted == labels).sum().item()\n",
    "    acc = correct / total\n",
    "    tqdm.write('Clean Accuracy %.2f\\n' % (acc*100))\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
